﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace OliversCalculator
{
   public partial class CalcForm : Form
   {
      private enum Operation { Plus, Minus, Multiply, Divide, None };

      private double m_FirstOperand;         // the first operand for calculation
      private double m_Display;        // the number currently shown in the display (= 2nd operand for calculation)
      private Operation m_LastOp;      // the operator typed before entering the 2nd operand
      private bool m_EditMode;         // true if currently in the process of typing a number, false if displaying a result
         
      public CalcForm()
      {
         InitializeComponent();
         buttonComma.Tag = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
         buttonComma.Text = "&" + buttonComma.Tag;

         buttonClear_Click(null, null);
      }

      private void buttonNumeric_Click(object sender, EventArgs e)
      {
         if (m_EditMode == false)
         {
            // when entering the edit mode, clear the display from previous input or result
            m_EditMode = true;
            textBoxDisplay.Text = "";
         }

         Button b = sender as Button;         
         String org = textBoxDisplay.Text;
         String key = b.Tag as String;

         try
         {
            m_Display = double.Parse(org + key);
         }
         catch (Exception ex)
         {
            // special case: only a decimal point typed (leading zero omitted)
            if (org + key == buttonComma.Tag)
            {
               textBoxDisplay.Text = "0" + key;
               return;
            }
            else
            {
               DisplayError();
               return;
            }
         }
         textBoxDisplay.Text = org + key;
      }

      private void DisplayError()
      {
         textBoxDisplay.Text = "Error";
         m_Display = 0.0;
         m_FirstOperand  = 0.0;
         m_LastOp = Operation.None;
         m_EditMode = false;
      }


      private void buttonClear_Click(object sender, EventArgs e)
      {
         textBoxDisplay.Text = "0";
         m_FirstOperand = 0.0;
         m_Display = 0.0;
         m_EditMode = false;
         m_LastOp = Operation.None;
      }

      private void buttonNeg_Click(object sender, EventArgs e)
      {
         m_Display = -m_Display;
         UpdateDisplay();
         m_EditMode = true;
      }

      private void UpdateDisplay()
      {
         textBoxDisplay.Text = m_Display.ToString(System.Globalization.CultureInfo.CurrentCulture);
      }

      private void PerformCalculation()
      {
         try
         {
            switch (m_LastOp)
            {
               case Operation.Plus:
                  m_Display = m_FirstOperand + m_Display;
                  break;
               case Operation.Minus:
                  m_Display = m_FirstOperand - m_Display;
                  break;
               case Operation.Multiply:
                  m_Display = m_FirstOperand * m_Display;
                  break;
               case Operation.Divide:
                  m_Display = m_FirstOperand / m_Display;
                  break;
               case Operation.None:
                  break;
            }
         }
         catch ( Exception ex )
         {
            // TODO: we never come here because .NET does not throw on divide by zero or infinity
            DisplayError();
            return;
         }

         m_FirstOperand = m_Display;
         UpdateDisplay();
         m_EditMode = false;
      }

 
      private void buttonOperation_Click(object sender, EventArgs e)
      {
         if (m_EditMode == true)
         {
            PerformCalculation();
         }

         Button b = sender as Button;
         switch (b.Tag as string)
         {
            case "Plus": m_LastOp = Operation.Plus; break;
            case "Minus": m_LastOp = Operation.Minus; break;
            case "Multiply": m_LastOp = Operation.Multiply; break;
            case "Divide": m_LastOp = Operation.Divide; break;
            case "Equals": m_LastOp = Operation.None; break;
         }
      }
   }
}
